go to index

Functions and Getting Help

read time 13 min read
Kaggle Python

Functions and Getting Help

您已经看到并使用了print和abs之类的函数。但是Python有更多的函数,定义您自己的函数是Python编程的重要组成部分。

在本课中,您将学习更多关于使用和定义函数的知识。

Getting Help

在之前的教程中您已经看到了abs函数,但是如果您忘记了它的作用怎么办?

help()函数可能是您可以学习的最重要的Python函数。如果您能记住如何使用help(),您就掌握了理解大多数其他函数的关键。

下面是一个例子:

python
help(round)
python
Help on built-in function round in module builtins:

round(number, ndigits=None)
    Round a number to a given precision in decimal digits.
    
    The return value is an integer if ndigits is omitted or None.  Otherwise
    the return value has the same type as the number.  ndigits may be negative.

Help()显示两件事:

  1. round函数的header round(number, ndigits=None)。在本例中,这告诉我们round()接受一个参数,我们可以将其描述为number。另外,我们可以选择给出一个单独的参数,可以描述为ndigits。
  2. 函数功能的简短英文描述。

常见的陷阱:当您查找一个函数时,记住传入函数本身的名称,而不是调用该函数的结果。

如果我们在调用round()函数时调用帮助,会发生什么?

python
help(round(-2.01))

这会出现一长串的代码,长到我在这里写不下…但他的大意是

Python从内到外计算这样的表达式。首先,它计算round的值(-2.01),然后为该表达式的输出提供帮助。

(事实证明,关于整数有很多要说的!在我们稍后讨论Python中的对象、方法和属性之后,上面的帮助输出将更有意义。)

Round是一个非常简单的函数,带有一个简短的文档字符串。在处理更复杂、可配置的功能(如打印)时,Help会更加出色。如果下面的输出看起来难以理解,不要担心…现在,看看你能否从这个帮助中找到新的东西。

python
help(print)
python
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

如果您正在查找它,您可能会了解到print可以接受一个名为sep的参数,并且它描述了我们在打印所有其他参数时在它们之间放置的内容。

Defining functions

内置函数很棒,但是在我们需要开始定义我们自己的函数之前,我们只能使用它们到此为止。下面是一个简单的例子用来说明如何定义函数。

python
def least_difference(a, b, c):
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    return min(diff1, diff2, diff3)

这将创建一个名为least_difference的函数,该函数接受三个参数:a、b和c。

函数以def关键字引入的头文件开始。:后面的缩进代码块在调用函数时运行。

Return是与函数唯一关联的另一个关键字。当Python遇到return语句时,它会立即退出函数,并将右侧的值传递给调用上下文。

从源代码中是否清楚least_difference()的作用?如果我们不确定,我们可以在几个例子上尝试一下:

python
print(
    least_difference(1, 10, 100),
    least_difference(1, 10, 10),
    least_difference(5, 6, 7), # Python allows trailing commas in argument lists. How nice is that?
)
plaintext
9 0 1

或者help()函数可以告诉我们一些有关它的信息。

python
help(least_difference)
python
Help on function least_difference in module __main__:

least_difference(a, b, c)

Python不够聪明,无法阅读我的代码并将其转换为漂亮的英文描述。然而,在编写函数时,我可以在文档字符串(docstring)中提供描述。

python
def least_difference(a, b, c):
    """Return the smallest difference between any two numbers
    among a, b and c.
    
    >>> least_difference(1, 5, -5)
    4
    """
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    return min(diff1, diff2, diff3)

文档字符串(docstring)是一个三重引号字符串(可以跨多行),紧跟在函数头之后。在函数上调用help()时,会显示文档字符串。

python
help(least_difference)
python
Help on function least_difference in module __main__:

least_difference(a, b, c)
    Return the smallest difference between any two numbers
    among a, b and c.
    
    >>> least_difference(1, 5, -5)
    4

旁白:文档字符串的最后两行是一个示例函数调用和结果。(>>>是对Python交互式shell中使用的命令提示符的引用。)Python不会运行示例调用——它只是为了方便读者。在函数文档字符串中包含一个或多个示例调用的约定并不普遍,但它可以非常有效地帮助别人理解你的函数。有关实际示例,请参阅numpy函数np.eye的文档字符串。

优秀的程序员会使用文档字符串,除非他们希望在代码使用后很快就把它扔掉(这种情况很少见)。因此,你也应该开始编写文档字符串!

Functions that don’t return

如果函数中不包含return关键字会发生什么?

python
def least_difference(a, b, c):
    """Return the smallest difference between any two numbers
    among a, b and c.
    """
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    min(diff1, diff2, diff3)
    
print(
    least_difference(1, 10, 100),
    least_difference(1, 10, 10),
    least_difference(5, 6, 7),
)
plaintext
None None None

Python允许我们定义这样的函数。调用它们的结果是一个特殊值None。(这类似于其他语言中的“null”的概念。)

如果没有return语句,least_difference是完全没有意义的,但有其他作用的函数可能做一些有用的事情却没有返回任何东西。我们已经见过两个这样的例子:print()和help()不返回任何东西。我们只因为它们的副作用(在屏幕上显示一些文本)调用它们。其他有用的副作用包括写入文件或修改输入。

python
mystery = print()
print(mystery)
plaintext
None

Default arguments

调用help(print)时,我们看到print函数有几个可选参数。例如,我们可以指定sep的值,在打印的参数之间放一些特殊的字符串:

python
print(1, 2, 3, sep=' < ')
plaintext
1 < 2 < 3

但如果我们不指定值,sep将被视为具有默认值(单个空格)。

python
print(1, 2, 3)
plaintext
1 2 3

给我们定义的函数添加带默认值的可选参数其实很简单:

python
def greet(who="Colin"):
    print("Hello,", who)
    
greet()
greet(who="Kaggle")
# (In this case, we don't need to specify the name of the argument, because it's unambiguous.)
greet("world")
plaintext
Hello, Colin
Hello, Kaggle
Hello, world

Functions Applied to Functions

这是一个很强大的东西,尽管一开始可能会觉得很抽象。你可以将函数作为参数提供给其他函数。举个例子可能会更清楚:

python
def mult_by_five(x):
    return 5 * x

def call(fn, arg):
    """Call fn on arg"""
    return fn(arg)

def squared_call(fn, arg):
    """Call fn on the result of calling fn on arg"""
    return fn(fn(arg))

print(
    call(mult_by_five, 1),
    squared_call(mult_by_five, 1), 
    sep='\n', # '\n' is the newline character - it starts a new line
)
plaintext
5
25

作用于其他函数的函数称为“高阶函数”。你可能一时半会不会自己写。不过,Python内置了一些高阶函数,你可能会发现调用它们很有用。

下面是一个使用max函数的有趣示例。

默认情况下,max返回最大的参数。但如果我们传入一个使用可选参数key的函数,它会返回最大化key(x)的参数x(又名argmax)。

python
def mod_5(x):
    """Return the remainder of x after dividing by 5"""
    return x % 5

print(
    'Which number is biggest?',
    max(100, 51, 14),
    'Which number is the biggest modulo 5?',
    max(100, 51, 14, key=mod_5),
    sep='\n',
)
plaintext
Which number is biggest?
100
Which number is the biggest modulo 5?
14

Exercise

Question 1

根据下面函数的文档字符串完成函数体。

提示:Python有一个内置函数round。

python
def round_to_two_places(num):
    """Return the given number rounded to two decimal places. 
    
    >>> round_to_two_places(3.14159)
    3.14
    """
    # Replace this body with your own code.
    # ("pass" is a keyword that does literally nothing. We used it as a placeholder
    # because after we begin a code block, Python requires at least one line of code)
    pass
    return round(num,2)

# Check your answer
q1.check()

Question 2

round的帮助说明说明ndigits(第二个参数)可以是负数。你觉得到时候会发生什么?尝试以下单元格中的一些示例。

python
# Put your test code here
round(3.1415926,-2)
plaintext
0.0

Question 3

在之前的练习中,分享糖果的朋友爱丽丝,鲍勃和卡罗尔试图平均分配糖果。为了他们的友谊,剩下的糖果都会被砸碎。例如,如果他们一起带回家91个糖果,他们将每人拿走30个,然后打碎1个。

下面是一个简单的函数,它将计算出任意数量的糖果要粉碎的糖果数量。

修改它,使其可选地接受第二个参数,表示正在分配糖果的朋友的数量。如果没有提供第二个参数,它应该像以前一样假设3个朋友。

更新文档字符串以反映这种新行为。

python
def to_smash(total_candies,num = 3):
    """Return the number of leftover candies that must be smashed after distributing
    the given number of candies evenly between 3 friends.
    
    >>> to_smash(91)
    1
    >>> to_smash(91,4)
    3
    """
    return total_candies % num

# Check your answer
q3.check()

Question 4

这可能并不有趣,但阅读和理解错误消息将是您的Python职业生涯的重要组成部分。

下面的每个代码单元都包含一些有注释的错误代码。对于每个细胞…

  • 阅读代码并预测运行时您认为会发生什么。
  • 然后取消对代码的注释并运行它,看看会发生什么。(提示:在内核编辑器中,您可以突出显示几行并按ctrl+/切换注释。)
  • 修复代码(以便在不抛出异常的情况下完成其预期目的)
python
ruound_to_two_places(9.9999)
python
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 ruound_to_two_places(9.9999)

NameError: name 'ruound_to_two_places' is not defined

fit:

python
round_to_two_places(9.9999)
python
x = -10
y = 5
# # Which of the two variables above has the smallest absolute value?
smallest_abs = min(abs(x, y))
python
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[16], line 4
      2 y = 5
      3 # # Which of the two variables above has the smallest absolute value?
----> 4 smallest_abs = min(abs(x, y))

TypeError: abs() takes exactly one argument (2 given)

fit:

python
x = -10
y = 5
# # Which of the two variables above has the smallest absolute value?
smallest_abs = min(abs(x),abs(y))
print(smallest_abs)
python
x = -10
y = 5
# # Which of the two variables above has the smallest absolute value?
smallest_abs = min(abs(x),abs(y))
print(smallest_abs)
python
 Cell In[20], line 3
    return y
    ^
SyntaxError: 'return' outside function

fit:

python
def f(x):
    y = abs(x)
    return y

print(f(5))